<%# locals: (action:, form_elements:, option_tree:, option_parents:, method: "POST", pre_selected_values: {}, mode: "create") %>
<% nonce = SecureRandom.hex(32)
content_security_policy.add_script_src [:nonce, nonce] %>

<script nonce="<%= nonce %>">
let option_tree = <%== allow_unescaped(JSON.generate(option_tree)) %>
let option_children = <%== allow_unescaped(JSON.generate(option_parents.each_with_object(Hash.new { |h, k| h[k] = [] }) { |(child, parents), h| h[parents.last] << child if parents.any? })) %>
let option_dirty = <%== allow_unescaped(JSON.generate(form_elements.map { it[:name] }.each_with_object(Hash.new { |h, k| h[k] = [] }) { |option, h| h[option] = typecast_body_params.str(option) || pre_selected_values[option] })) %>
</script>

<div>
  <div class="grid gap-6">
    <% form(action:, method:, id: "creation-form", class: method) do %>
      <% container_class = (mode == "create") ? "overflow-hidden rounded-lg shadow ring-1 ring-black ring-opacity-5 bg-white" : "" %>
      <div class="<%= container_class %>">
        <div class="px-4 py-5 sm:p-6">
          <div class="space-y-12">
            <div>
              <div class="mt-2 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
                <% selected_options = {}
  pre_selected_values.each { |k, v| selected_options[k] = v.to_s }

  form_elements.each do |element|
    container_opening_tag = element[:opening_tag] || "<div class='col-span-full'>"
    container_closing_tag = element[:closing_tag] || "</div>"

    name, type, label, required, placeholder, content_generator = element.values_at(:name, :type, :label, :required, :placeholder, :content_generator)

    has_option = ["radio_small_cards", "select", "checkbox"].include?(type)
    options = OptionTreeGenerator.generate_allowed_options(name, option_tree, option_parents).map do |option|
      opt_val = if option[name].is_a?(Sequel::Model)
        option[name].ubid
      elsif type == "select"
        option[name][:value]
      else
        option[name]
      end

      opt_text = content_generator.call(*option.values)

      parents = option.reject { |k, v| k == name }.transform_values { |v| v.is_a?(Sequel::Model) ? v.ubid : v }

      parents_selected = parents.all? { |k, v| selected_options[k] == v }
      submitted_value = typecast_body_params.str(name)
      selected_in_form_submission = submitted_value == opt_val
      selected_in_pre_selection = submitted_value.nil? && selected_options[name] == opt_val
      first_of_its_kind = submitted_value.nil? && selected_options[name].nil? unless type == "checkbox" && !request.get?
      checked = parents_selected && (selected_in_form_submission || selected_in_pre_selection || first_of_its_kind)
      selected_options[name] = opt_val if checked

      opt_classes = parents.map { |k, v| "form_#{k} form_#{k}_#{v.tr(".", "-")}" }
      opt_classes << "hidden" unless parents_selected
      opt_classes = opt_classes.join(" ")

      opt_attrs = {}
      opt_attrs[:disabled] = "disabled" unless parents_selected
      opt_attrs[:checked] = checked

      [opt_val, opt_text, opt_classes, opt_attrs]
    end if has_option

    attributes = {required:}

    case type
    when "radio_small_cards"
      locals = {name:, label:, options:, attributes:, description_html: element[:description_html], additional_element_html: element[:additional_element_html]}
    when "select"
      locals = {name:, label:, options:, placeholder:, attributes:, description_html: element[:description_html]}
    when "checkbox"
      locals = {name:, label:, options:, description: element[:description]}
    when "text"
      locals = {name:, label:, value: element[:value], attributes: attributes.merge!({placeholder:})}
    when "number"
      locals = {name:, label:, type: "number", attributes: attributes.merge!({placeholder:})}
      type = "text"
    when "textarea"
      locals = {name:, label:, description: element[:description], escape_description: element.fetch(:escape_description, true), attributes: attributes.merge!({placeholder:, rows: 3})}
    when "hidden"
      selected_options[name] = element[:value]
      locals = {name => element[:value]}
      container_opening_tag, container_closing_tag = "", ""
    when "partnership_notice"
      description_html, tos_text = content_generator.call(@flavor)
      locals = {description_html:, tos_text:}
    when "section"
      locals = {label:, content: element[:content], separator: element[:separator]}
    # :nocov:
    else
      raise "Unknown element type: #{type}"
    # :nocov:
    end %>
                  <%== container_opening_tag %>
                  <%== part("components/form/#{type}", **locals) %>
                  <%== container_closing_tag %>
                <% end %>
              </div>
            </div>
          </div>
        </div>
        <div class="px-4 py-5 sm:p-6">
          <div class="flex items-center justify-end gap-x-6">
            <% if mode == "create" %>
              <a href="<%= action %>" class="text-sm font-semibold leading-6 text-gray-900">Cancel</a>
              <%== part("components/form/submit_button", text: "Create") %>
            <% else %>
              <%== part("components/form/submit_button", text: "Update") %>
            <% end %>
          </div>
        </div>
      </div>
    <% end %>
  </div>
</div>
